package com.xdf.xzymanagementsystem.service.impl;

import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.xdf.xzymanagementsystem.dao.*;
import com.xdf.xzymanagementsystem.entity.*;
import com.xdf.xzymanagementsystem.service.GreyMainService;
import com.xdf.xzymanagementsystem.service.OrderMainService;
import com.xdf.xzymanagementsystem.util.CodeGenUtil;
import com.xdf.xzymanagementsystem.util.SystemUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 服务层实现类，由代码生成器自动生成
 * @Author : chanchaw
 * @Date : 2025-3-21 18:43:41
 */
@Slf4j
@Service
public class GreyMainServiceImpl extends ServiceImpl<GreyMainMapper, GreyMain> implements GreyMainService {
    @Autowired
    private GreyMainMapper dao;
    @Autowired
    private GreyDetailMapper greyDetailMapper;
    @Autowired
    private SystemUtils systemUtils;
    @Autowired
    private CodeGenUtil codeGenUtil;
    @Autowired
    private OrderMainMapper orderMainMapper;
    //=================以上是自动生成的代码，自定义代码请写在下面==================
    @Override
    public List<Map<String, Object>> selectAllDTO(Date sdate, Date edate, int flag) {
        return dao.selectAllDTO(sdate, edate, flag);
    }

    //新增单据
    @Override
    @Transactional(rollbackFor = Exception.class)
    public GreyMainDTO insertDTO(GreyMainDTO record) throws Exception {
//        if (selectRepeatOrderNo(record.getOrderNo()) != null) throw new RuntimeException("订单号已存在,不允许重复！！");
        GreyMain greyMain = new GreyMain();
        BeanUtils.copyProperties(record, greyMain);
        greyMain.setCreateUser(systemUtils.getLoginUsername());
        greyMain.setState(1);
        greyMain.setBillCode(getBillCode());
        dao.insertSelective(greyMain);//新增主表数据
        List<GreyDetail> detailList = record.getDetailList();
        for (GreyDetail greyDetail : detailList) {
            greyDetail.setParentId(greyMain.getId());//关联主表id
            greyDetail.setState(1);
            greyDetail.setCreateUser(systemUtils.getLoginUsername());
            greyDetailMapper.insertSelective(greyDetail);
        }
        //获取数据并返回
        GreyMainDTO greyMainDTO = selectDTO(greyMain.getId());
        return greyMainDTO;
    }

    //检测订单号是否重复
    private GreyMain selectRepeatOrderNo(String orderNo) {
        return dao.selectRepeatOrderNo(orderNo);
    }

    //生成单据编号
    private String getBillCode() {
        GreyMain greyMain = dao.selectMaxBillCode();
        int year = LocalDate.now().getYear();
        int monthValue = LocalDate.now().getMonthValue();
        int day = LocalDate.now().getDayOfMonth();
        if (greyMain != null) {
            String billCode = greyMain.getBillCode();
            int codeNumber = Integer.parseInt(billCode.substring(8));
            int dayNumber = Integer.parseInt(billCode.substring(6, 8));
            if (dayNumber != day) {
                codeNumber = 0;
            }
            return "BP" + String.valueOf(year).substring(2) + String.format("%02d", monthValue) + String.format("%02d", day)  + String.format("%03d", codeNumber + 1);
        }else {
            return "BP" + String.valueOf(year).substring(2) + String.format("%02d", monthValue) + String.format("%02d", day)  + String.format("%03d", 1);
        }
    }

    @Override
    public GreyMainDTO selectDTO(Integer id) {
        GreyMainDTO greyMainDTO = new GreyMainDTO();
        GreyMain main = dao.selectById(id);//查询主表
        List<GreyDetail> details = greyDetailMapper.selectByParentId(id);
        for (GreyDetail detail : details) {
            if (detail.getInventoryId() != null) {
                GreyDetail greyDetail = greyDetailMapper.selectOneById(detail.getInventoryId());
                GreyMain greyMain = dao.selectById(greyDetail.getParentId());
                if (greyMain != null) detail.setSysRemark(greyMain.getBusinessSource());
            }
        }
        BeanUtils.copyProperties(main, greyMainDTO);
        greyMainDTO.setDetailList(details);
        return greyMainDTO;
    }

    //修改单据
    @Override
    @Transactional(rollbackFor = Exception.class)
    public GreyMainDTO updateDTO(GreyMainDTO record) {
//        GreyMain main = selectRepeatOrderNo(record.getOrderNo());
        //订单号相同，id不同
//        if (main != null) {
//            if (main.getOrderNo().equals(record.getOrderNo()) && !main.getId().equals(record.getId())) throw new RuntimeException("订单号已存在,不允许重复！！");
//        }
        List<GreyDetail> detailList = record.getDetailList();
        //检测修改的匹数、公斤、米数，是否超出库存
        if (detailList.size() > 0) {
            for (GreyDetail greyDetail : detailList) {
                if (greyDetail.getInventoryId() != null) {
                    GreyDetail detail = greyDetailMapper.selectOneById(greyDetail.getInventoryId());
                    if (detail.getKilo().compareTo(greyDetail.getKilo()) < 0 ||
                            detail.getPiece().compareTo(greyDetail.getPiece()) < 0) throw new RuntimeException("输入的匹数或公斤超出库存，请检查！！");
                }
            }
        }

        GreyMain greyMain = new GreyMain();
        BeanUtils.copyProperties(record, greyMain);
        greyMain.setUpdateTime(new Date());
        greyMain.setUpdateUser(systemUtils.getLoginUsername());
        if (dao.update(greyMain) < 0) throw new RuntimeException("修改主表时发生错误！");
        for (GreyDetail greyDetail : detailList) {
            if (Optional.ofNullable(greyDetail.getId()).orElse(0) == 0) {
                greyDetail.setParentId(greyMain.getId());//关联主表id
                greyDetail.setState(1);
                greyDetail.setCreateUser(systemUtils.getLoginUsername());
                greyDetailMapper.insertSelective(greyDetail);
            }
            greyDetail.setUpdateTime(new Date());
            greyDetail.setUpdateUser(systemUtils.getLoginUsername());
            if (greyDetailMapper.update(greyDetail) < 0) throw new RuntimeException("修改明细时发生错误！");
        }
        List<GreyDetail> details = greyDetailMapper.selectByParentId(record.getId());
        //删除掉删除行的明细
        List<GreyDetail> extraDetails = getDeleteDetails(detailList, details);
        if (extraDetails.size() > 0) {
            for (GreyDetail extraDetail : extraDetails) {
                greyDetailMapper.deleteById(extraDetail.getId());
            }
        }
        return selectDTO(record.getId());
    }

    //查询过滤删除行的明细
    private static List<GreyDetail> getDeleteDetails(List<GreyDetail> detailList, List<GreyDetail> details) {
        // 提取detailList中所有元素的ID集合
        Set<Integer> detailIds = detailList.stream()
                .map(GreyDetail::getId)
                .collect(Collectors.toSet());
        // 过滤出details中ID不在detailIds的元素
        List<GreyDetail> extraDetails = details.stream()
                .filter(d -> !detailIds.contains(d.getId()))
                .collect(Collectors.toList());
        return extraDetails;
    }

    //批量删除
    @Override
    public void deleteByIds(List<Integer> ids) {
        for (Integer id : ids) {
            GreyMain greyMain = dao.selectById(id);
            if (!greyMain.getBillType().equals("白坯期初入库") && !greyMain.getBillType().equals("白坯入库单") && !greyMain.getBillType().equals("白坯盘点单")&& !greyMain.getBillType().equals("本厂白坯退货")) {
                OrderMain orderMain = orderMainMapper.selectRepeatOrderNo(greyMain.getOrderNo());
                if (orderMain.getState() == 2) throw new RuntimeException("该订单已完成，不允许删除！！");
            }
            List<GreyDetail> details = greyDetailMapper.selectByParentId(id);
            if (details.size() > 0) {
                for (GreyDetail detail : details) {
                    detail.setIsDelete(1);
                    detail.setUpdateUser(systemUtils.getLoginUsername());
                    detail.setUpdateTime(new Date());
                    greyDetailMapper.update(detail);
                }
            }
            greyMain.setIsDelete(1);
            greyMain.setUpdateUser(systemUtils.getLoginUsername());
            greyMain.setUpdateTime(new Date());
            dao.update(greyMain);
        }
    }

    @Override
    public List<Map<String, Object>> selectInventory() {
        return dao.selectInventory();
    }
}